package org.ramoths.netcom.sessions;

import java.net.Socket;

import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.util.PublicKeyFactory;
import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory;
import org.ramoths.netcom.outils.Outils;

public class SessionInit
{
	public static SessionParametres initialiserSession(Socket socket) throws Exception
	{
		try
		{
			byte[] tmp = null;
			int tmp2 = 0;
			//
			socket.setKeepAlive(true);
			socket.setSoTimeout(30000);
			//
			// Envoi de la cle publique locale
			SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(Outils.getClePubliqueCrypt());
			tmp = info.toASN1Primitive().getEncoded("DER");
			socket.getOutputStream().write(Outils.desInt(tmp.length));
			socket.getOutputStream().write(tmp);
			//
			// Reception de la cle publique distante
			tmp2 = Outils.assInt(Outils.lectureFlux(socket.getInputStream(), 4), 0);
			tmp = Outils.lectureFlux(socket.getInputStream(), tmp2);
			RSAKeyParameters clePubliqueDistante = (RSAKeyParameters) PublicKeyFactory.createKey(tmp);
			//
			// Génération de la clé et la séquences locales
			byte[] cleLocale = new byte[32]; Outils.getSRand().nextBytes(cleLocale);
			long sequenceIVLocale = Outils.getSRand().nextLong();
			//
			tmp = Outils.crypterRSA(cleLocale, clePubliqueDistante);
			socket.getOutputStream().write(Outils.desInt(tmp.length));
			socket.getOutputStream().write(tmp);
			//
			tmp = Outils.crypterRSA(Outils.desLong(sequenceIVLocale), clePubliqueDistante);
			socket.getOutputStream().write(Outils.desInt(tmp.length));
			socket.getOutputStream().write(tmp);
			//
			// Récupération de la clé et la séquence distante
			tmp2 = Outils.assInt(Outils.lectureFlux(socket.getInputStream(), 4), 0);
			byte[] cleDistante = Outils.decrypterRSA(Outils.lectureFlux(socket.getInputStream(), tmp2));
			//
			tmp2 = Outils.assInt(Outils.lectureFlux(socket.getInputStream(), 4), 0);
			long sequenceIVDistante = Outils.assLong(Outils.decrypterRSA(Outils.lectureFlux(socket.getInputStream(), tmp2)), 0);
			//
			//
			socket.setSoTimeout(0);
			//
			return new SessionParametres(cleLocale, sequenceIVLocale, cleDistante, sequenceIVDistante);
		}
		catch (Exception ex)
		{
			throw new Exception("Erreur d'initialisation de la session!", ex);
		}
	}
}
